home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / unix / cpp / part04 < prev    next >
Encoding:
Internet Message Format  |  1990-01-18  |  29.2 KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i025: cpp - a c preprocessor with some ANSI features, Part04/05
  5. Message-ID: <11033@xanth.cs.odu.edu>
  6. Date: 18 Jan 90 00:21:15 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
  9. Lines: 839
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11.  
  12. Submitted-by: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
  13. Posting-number: Volume 90, Issue 025
  14. Archive-name: unix/cpp/part04
  15.  
  16. #!/bin/sh
  17. # This is a shell archive.  Remove anything before this line, then unpack
  18. # it by saving it into a file and typing "sh file".  To overwrite existing
  19. # files, type "sh file -c".  You can also feed this as standard input via
  20. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  21. # will see the following message at the end:
  22. #        "End of archive 4 (of 5)."
  23. # Contents:  Cpp1.c
  24. # Wrapped by tadguy@xanth on Wed Jan 17 19:17:37 1990
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'Cpp1.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'Cpp1.c'\"
  28. else
  29. echo shar: Extracting \"'Cpp1.c'\" \(26903 characters\)
  30. sed "s/^X//" >'Cpp1.c' <<'END_OF_FILE'
  31. X/*
  32. X * CPP main program.
  33. X *
  34. X * Edit history
  35. X * 21-May-84    MM    "Field test" release
  36. X * 23-May-84    MM    Some minor hacks.
  37. X * 30-May-84    ARF    Didn't get enough memory for __DATE__
  38. X *            Added code to read stdin if no input
  39. X *            files are provided.
  40. X * 29-Jun-84    MM    Added ARF's suggestions, Unixifying cpp.
  41. X * 11-Jul-84    MM    "Official" first release (that's what I thought!)
  42. X * 22-Jul-84    MM/ARF/SCK Fixed line number bugs, added cpp recognition
  43. X *            of #line, fixed problems with #include.
  44. X * 23-Jul-84    MM    More (minor) include hacking, some documentation.
  45. X *            Also, redid cpp's #include files
  46. X * 25-Jul-84    MM    #line filename isn't used for #include searchlist
  47. X *            #line format is <number> <optional name>
  48. X * 25-Jul-84    ARF/MM    Various bugs, mostly serious.  Removed homemade doprint
  49. X * 01-Aug-84    MM    Fixed recursion bug, remove extra newlines and
  50. X *            leading whitespace from cpp output.
  51. X * 02-Aug-84    MM    Hacked (i.e. optimized) out blank lines and unneeded
  52. X *            whitespace in general.    Cleaned up unget()'s.
  53. X * 03-Aug-84    Keie    Several bug fixes from Ed Keizer, Vrije Universitet.
  54. X *            -- corrected arg. count in -D and pre-defined
  55. X *            macros.  Also, allow \n inside macro actual parameter
  56. X *            lists.
  57. X * 06-Aug-84    MM    If debugging, dump the preset vector at startup.
  58. X * 12-Aug-84    MM/SCK    Some small changes from Sam Kendall
  59. X * 15-Aug-84    Keie/MM cerror, cwarn, etc. take a single string arg.
  60. X *            cierror, etc. take a single int. arg.
  61. X *            changed LINE_PREFIX slightly so it can be
  62. X *            changed in the makefile.
  63. X * 31-Aug-84    MM    USENET net.sources release.
  64. X *  7-Sep-84    SCH/ado Lint complaints
  65. X * 10-Sep-84    Keie    Char's can't be signed in some implementations
  66. X * 11-Sep-84    ado    Added -C flag, pathological line number fix
  67. X * 13-Sep-84    ado    Added -E flag (does nothing) and "-" file for stdin.
  68. X * 14-Sep-84    MM    Allow # 123 as a synonym for #line 123
  69. X * 19-Sep-84    MM    scanid always reads to token, make sure #line is
  70. X *            written to a new line, even if -C switch given.
  71. X *            Also, cpp - - reads stdin, writes stdout.
  72. X * 03-Oct-84    ado/MM    Several changes to line counting and keepcomments
  73. X *            stuff.    Also a rewritten control() hasher -- much
  74. X *            simpler and no less "perfect". Note also changes
  75. X *            in cpp3.c to fix numeric scanning.
  76. X * 04-Oct-84    MM    Added recognition of macro formal parameters if
  77. X *            they are the only thing in a string, per the
  78. X *            draft standard.
  79. X * 08-Oct-84    MM    One more attack on scannumber
  80. X * 15-Oct-84    MM/ado    Added -N to disable predefined symbols.  Fixed
  81. X *            linecount if COMMENT_INVISIBLE enabled.
  82. X * 22-Oct-84    MM    Don't evaluate the #if/#ifdef argument if
  83. X *            compilation is supressed.  This prevents
  84. X *            unnecessary error messages in sequences such as
  85. X *                #ifdef FOO        -- undefined
  86. X *                #if FOO == 10    -- shouldn't print warning
  87. X * 25-Oct-84    MM    Fixed bug in false ifdef supression.  On vms,
  88. X *            #include <foo> should open foo.h -- this duplicates
  89. X *            the behavior of Vax-C
  90. X * 31-Oct-84    ado/MM    Parametized $ in indentifiers.    Added a better
  91. X *            token concatenator and took out the trial
  92. X *            concatenation code.  Also improved #ifdef code
  93. X *            and cleaned up the macro recursion tester.
  94. X *  2-Nov-84    MM/ado    Some bug fixes in token concatenation, also
  95. X *            a variety of minor (uninteresting) hacks.
  96. X *  6-Nov-84    MM    Happy Birthday.  Broke into 4 files and added
  97. X *            #if sizeof (basic_types)
  98. X *  9-Nov-84    MM    Added -S* for pointer type sizes
  99. X * 13-Nov-84    MM    Split cpp1.c, added vms defaulting
  100. X * 23-Nov-84    MM/ado    -E supresses error exit, added CPP_INCLUDE,
  101. X *            fixed strncpy bug.
  102. X *  3-Dec-84    ado/MM    Added OLD_PREPROCESSOR
  103. X *  7-Dec-84    MM    Stuff in Nov 12 Draft Standard
  104. X * 17-Dec-84    george    Fixed problems with recursive macros
  105. X * 17-Dec-84    MM    Yet another attack on #if's (f/t)level removed.
  106. X * 07-Jan-85    ado    Init defines before doing command line options
  107. X *            so -Uunix works.
  108. X * 21-Oct-85    RMS    Rename `token' to `tokenbuf'.
  109. X *            Allocate it dynamically, with size in `tokenbsize'.
  110. X * 23-Oct-85    RMS    Do not print message about number of errors.
  111. X * 14-Mar-85    FNF    Incorporate macro based C debugging package.
  112. X *            Port to Commodore AMIGA.
  113. X * 20-Aug-88    Ois    Changed format of documentation.
  114. X */
  115. X
  116. X/*)BUILD
  117. X    $(PROGRAM)      = cpp
  118. X    $(FILES)        = { cpp1 cpp2 cpp3 cpp4 cpp5 cpp6 }
  119. X    $(INCLUDE)      = { cppdef.h cpp.h }
  120. X    $(STACK)        = 2000
  121. X    $(TKBOPTIONS)   = {
  122. X        STACK    = 2000
  123. X    }
  124. X*/
  125. X
  126. X#ifdef    DOCUMENTATION
  127. X.TH CPP 1 "Amiga Programmer's Manual" "1st PDC distribution"
  128. X.SH NAME
  129. X.bo "cpp
  130. X- C Pre Processor. Macro-preprocess C programs.
  131. X.SH SYNOPSIS
  132. X.nf
  133. Xcpp [-options] [infile [outfile]]
  134. X.fi
  135. X.SH DESCRIPTION
  136. XCPP reads a C source file, expands macros and include files, and writes an
  137. Xinput file for the C compiler. If no file arguments are given, CPP reads
  138. Xfrom stdin and writes to stdout.  If one file argument is given, it will
  139. Xdefine the input file, while two file arguments define both input and
  140. Xoutput files.  The file name "-" is a synonym for stdin or stdout as
  141. Xappropriate.
  142. X
  143. XThe following options are supported.  Options may be given in either case.
  144. X.in +5
  145. X.ta +0
  146. X.sp
  147. X.ti -5
  148. X-C@tIf set, source-file comments are written to the output file.  This
  149. Xallows the output of CPP to be used as the input to a program, such as
  150. Xlint, that expects commands embedded in specially-formatted comments.
  151. X.sp
  152. X.ti -5
  153. X-Dname=value
  154. X.br
  155. XDefine the name as if the programmer wrote
  156. X
  157. X    #define name value
  158. X
  159. Xat the start of the first file.  If "=value" is not given, a value of "1"
  160. Xwill be used.
  161. X
  162. XOn non-unix and non-amiga systems, all alphabetic text will be forced to
  163. Xupper-case.
  164. X.sp
  165. X.ti -5
  166. X-E@tAlways return "success" to the operating system, even if errors were
  167. Xdetected.  Note that some fatal errors, such as a missing #include file,
  168. Xwill terminate CPP, returning "failure" even if the -E option is given.
  169. X.sp
  170. X.ti -5
  171. X-Idirectory
  172. X.br
  173. XAdd this directory to the list of directories searched for #include "..."
  174. Xand #include <...> commands.  Note that there is no space between the "-I"
  175. Xand the directory string.  More than one -I command is permitted.  On
  176. Xnon-Unix systems "directory" is forced to upper-case.
  177. X.sp
  178. X.ti -5
  179. X-N@tCPP normally predefines some symbols defining the target computer and
  180. Xoperating system.  If -N is specified, no symbols will be predefined.  If
  181. X-N -N is specified, the "always present" symbols, __LINE__, __FILE__,
  182. X__TIME__ and __DATE__ are not defined.
  183. X.sp
  184. X.ti -5
  185. X-Stext
  186. X.br
  187. XCPP normally assumes that the size of the target computer's basic variable
  188. Xtypes is the same as the size of these types of the host computer.  (This
  189. Xcan be overridden when CPP is compiled, however.)  The -S option allows
  190. Xdynamic respecification of these values.  "text" is a string of numbers,
  191. Xseparated by commas, that specifies correct sizes. The sizes must be
  192. Xspecified in the exact order:
  193. X
  194. X    char short int long float double
  195. X
  196. XIf you specify the option as "-S*text", pointers to these types will be
  197. Xspecified.  -S* takes one additional argument for pointer to function (e.g.
  198. Xint (*)())
  199. X
  200. XFor example, to specify sizes appropriate for a PDP-11, you would write:
  201. X
  202. X       c s i l f d func
  203. X     -S1,2,2,2,4,8,
  204. X    -S*2,2,2,2,2,2,2
  205. X
  206. XNote that all values must be specified.
  207. X.br;.it -1
  208. XNote also that this is not allowed by the 11-Jan-88 Draft, and therefore
  209. Xhas made into an option when compiling Cpp.
  210. X.it 0
  211. X.sp
  212. X.ti -5
  213. X-Uname
  214. X.br
  215. XUndefine the name as if
  216. X
  217. X    #undef name
  218. X
  219. Xwere given.  On non-Unix systems, "name" will be forced to upper-case.
  220. X.sp
  221. X.ti -5
  222. X-Xnumber
  223. X.br
  224. XEnable debugging code.    If no value is given, a value of 1 will be used.
  225. X(For maintenence of CPP only.)
  226. X.in -5
  227. X.SH Pre-Defined Variables
  228. XWhen CPP begins processing, the following variables will have been defined
  229. X(unless the -N option is specified):
  230. X.sp
  231. XTarget computer (as appropriate):
  232. X.sp
  233. X    pdp11, vax, M68000 m68000 m68k, amiga
  234. X.sp
  235. XTarget operating system (as appropriate):
  236. X.sp
  237. X    rsx, rt11, vms, unix, amigados
  238. X.sp
  239. XTarget compiler (as appropriate):
  240. X.sp
  241. X    decus, vax11c, pdc PDC __PDC__
  242. X.sp
  243. XThe implementor may add definitions to this list. The default definitions
  244. Xmatch the definition of the host computer, operating system, and C
  245. Xcompiler.
  246. X.sp
  247. XThe following are always available unless undefined (or -N was specified
  248. Xtwice):
  249. X
  250. X.in +16
  251. X.ta
  252. X.ta +0
  253. X.ti -12
  254. X__FILE__@tThe input (or #include) file being compiled (as a quoted string).
  255. X.ti -12
  256. X__LINE__@tThe line number being compiled.
  257. X.ti -12
  258. X__DATE__@tThe date of compilation as a quoted string of the format
  259. X"Mmm dd yyyy".
  260. X.ti -12
  261. X__TIME__@tThe time of the start of compilation as a quoted string of the
  262. Xformat "hh:mm:ss". Thus,
  263. X.br
  264. X    printf("Bug at line %s,", __LINE__);
  265. X    printf(" source file %s", __FILE__);
  266. X    printf("@ compiled@ on@ %s@ %s", __DATE__, __TIME__);
  267. X.br
  268. X.in -16
  269. X.SH Supported directives
  270. X.br;    #assert <expression>
  271. X.br;    #define <token> <replacement>
  272. X.br;    #elif <expression>
  273. X.br;    #else <expression>
  274. X.br;    #endif
  275. X.br;    #error
  276. X.br;    #if <expression>
  277. X.br;    #ifdef <token>
  278. X.br;    #ifndef <token>
  279. X.br;    #include <filename>
  280. X.br;    #line <number> <filename>
  281. X.br;    #pragma <anything>
  282. X.br;    #undef <token>
  283. X.br;    #debug
  284. X.br;    #nodebug
  285. X.sp
  286. XUnsupported # commands are copied verbatim into the output, so that maybe
  287. Xthe compiler knows what to do with them.
  288. X.SH Draft Proposed Ansi Standard Considerations
  289. XThe current version of the Draft Proposed Standard explicitly states that
  290. X"readers are requested not to specify or claim conformance to this draft."
  291. XReaders and users of Decus CPP should not assume that Decus CPP conforms to
  292. Xthe standard, or that it will conform to the actual C Language Standard.
  293. X
  294. XWhen CPP is itself compiled, many features of the Draft Proposed Standard
  295. Xthat are incompatible with existing preprocessors may be disabled.  See the
  296. Xcomments in CPP's source for details.
  297. X
  298. XThe latest version of the Draft Proposed Standard (as reflected in Decus
  299. XCPP) is dated November 12, 1984, and bits from K&R V2 are put in by Ois.
  300. X
  301. XComments are removed from the input text.  The comment is replaced by a
  302. Xsingle space character.  The -C option preserves comments, writing them to
  303. Xthe output file.
  304. X
  305. XThe '$' character is considered to be a letter.  This is a permitted
  306. Xextension.
  307. X
  308. XThe following new features of C are processed by CPP:
  309. X.sp
  310. X.* The following .br commands are there so the preprocessor
  311. X.* does not get confused when compiling cpp1.c
  312. X.nf
  313. X.br;    #if, #elif
  314. X.br;    #elif expression    (#else #if)
  315. X.br;    '\xNNN'                 (Hexadecimal constant)
  316. X.br;    '\a'                    (Ascii BELL)
  317. X.br;    '\v'                    (Ascii Vertical Tab)
  318. X.br;    #if defined NAME    1 if defined, 0 if not
  319. X.br;    #if defined (NAME)      1 if defined, 0 if not
  320. X.br;    #if sizeof (basic type)
  321. X.br;    #error            Generates error message
  322. X.br;    unary +
  323. X.br;    123U, 123LU        Unsigned ints and longs.
  324. X.br;    12.3L            Long double numbers
  325. X.br;    token##token        Token concatenation in macros
  326. X.br;    #macro-formal        String generation in macros
  327. X.br;    #include token        Expands to filename
  328. X.fi
  329. X
  330. XThe Draft Proposed Standard has extended C, adding a constant string
  331. Xconcatenation operator, where
  332. X
  333. X    "foo" "bar"
  334. X
  335. Xis regarded as the single string "foobar".  (This does not affect CPP's
  336. Xprocessing but does permit a limited form of macro argument substitution
  337. Xinto strings as will be discussed.)
  338. X
  339. XThe Standard Committee plans to add token concatenation to #define command
  340. Xlines.    One suggested implementation is as follows:  the sequence
  341. X"Token1 ## Token2" is treated as if the programmer wrote "Token1Token2".
  342. X
  343. XThis could be used as follows:
  344. X
  345. X    #line 123
  346. X    #define ATLINE foo ## __LINE__
  347. X
  348. XATLINE would be defined as foo123.
  349. X
  350. XNote that "Token1" and "Token2" both must be valid tokens, but the
  351. Xconcatenation of their expanded forms may not be a _single_ valid token. In
  352. Xthat case, K&R state that the behaviour is undefined. So if you wish to
  353. Xmake portable use of this facility, do not do the following:
  354. X
  355. X    #define cat(x, y)   x ## y
  356. X    cat(foo, 1.23)
  357. X
  358. Xwhich will produce
  359. X
  360. X    foo1.23
  361. X
  362. Xand that is not a single token.
  363. X
  364. XIf the tokens T1 and T2 are concatenated into T3, this implementation
  365. Xoperates as follows:
  366. X
  367. X  1.@ Expand T1 if it is a macro.
  368. X  2.@ Expand T2 if it is a macro.
  369. X  3.@ Join the tokens, forming T3.
  370. X  4.@ Rescan T3, looking for tokens, that may be expanded again.
  371. X
  372. X      A macro formal parameter will be substituted into a string or
  373. Xcharacter constant if it is the only component of that constant:
  374. X
  375. X    #define VECSIZE 123
  376. X    #define vprint(name, size) \
  377. X      printf("name" "[" "size" "] = {\n")
  378. X      ... vprint(vector, VECSIZE);
  379. X
  380. Xexpands (effectively) to
  381. X
  382. X      vprint("vector[123] = {\n");
  383. X
  384. XNote that this will be useful if your C compiler supports the new string
  385. Xconcatenation operation noted above. As implemented here, if you write
  386. X
  387. X    #define string(arg) "arg"
  388. X      ... string("foo") ...
  389. X
  390. XThis implementation generates "foo", rather than the strictly correct
  391. X""foo"" (which will probably generate an error message). This is, strictly
  392. Xspeaking, an error in CPP and may be removed from future releases.
  393. X.it -1
  394. XNote that the above feature of replacing macro formals inside quotes is
  395. Xnon-standard. The Committee thought the following to be better:
  396. X.it 0
  397. X.sp
  398. XIf a macro formal argument is immediately preceeded by a #, the argument
  399. Xsupplied when expanding the macro will be surrounded by double quotes, and
  400. Xeach double quote or backslash will be preceeded by a backslash. An example
  401. Xof this would be:
  402. X
  403. X    #define string(arg) #arg
  404. X      ... string(foo) ...
  405. X
  406. Xwhich produces "foo". Note that this feature is useless if you want your
  407. Xstring to contain an odd number of quotes:
  408. X
  409. X    string(Hello");
  410. X
  411. Xwill produce an error message, complaining about unterminated strings.
  412. X
  413. X.SH Error messages
  414. XMany.  CPP prints warning or error messages if you try to use multiple-byte
  415. Xcharacter constants (non-transportable) if you #undef a symbol that was not
  416. Xdefined, or if your program has potentially nested comments.
  417. X.SH Author
  418. XMartin Minow, minor changes by RMS, FNF, OIS.
  419. X.SH Bugs
  420. XThe #if expression processor uses signed integers only.
  421. XI.e, #if 0xFFFFu < 0 may be TRUE.
  422. X#endif    /* DOCUMENTATION */
  423. X
  424. X#include    <stdio.h>
  425. X#include    <ctype.h>
  426. X#include    "cppdef.h"
  427. X#include    "cpp.h"
  428. X
  429. X/*
  430. X * Commonly used global variables:
  431. X * line     is the current input line number.
  432. X * wrongline    is set in many places when the actual output
  433. X *        line is out of sync with the numbering, e.g,
  434. X *        when expanding a macro with an embedded newline.
  435. X *
  436. X * tokenbuf    holds the last identifier scanned (which might
  437. X *        be a candidate for macro expansion).
  438. X * errors    is the running cpp error counter.
  439. X * infile    is the head of a linked list of input files (extended by
  440. X *        #include and macros being expanded).  infile always points
  441. X *        to the current file/macro.  infile->parent to the includer,
  442. X *        etc.  infile->fd is NULL if this input stream is a macro.
  443. X */
  444. Xint        line;            /* Current line number        */
  445. Xint        wrongline;        /* Force #line to compiler    */
  446. Xchar        *tokenbuf;        /* Buffer for current input token */
  447. Xint        tokenbsize;        /* Allocated size of tokenbuf, */
  448. X                    /* not counting zero at end.  */
  449. Xint        errors;         /* cpp error counter        */
  450. XFILEINFO    *infile = NULL;     /* Current input file        */
  451. X#if DEBUG
  452. Xint        debug;            /* TRUE if debugging now    */
  453. X#endif
  454. X/*
  455. X * This counter is incremented when a macro expansion is initiated.
  456. X * If it exceeds a built-in value, the expansion stops -- this tests
  457. X * for a runaway condition:
  458. X *    #define X Y
  459. X *    #define Y X
  460. X *    X
  461. X * This can be disabled by falsifying rec_recover.  (Nothing does this
  462. X * currently: it is a hook for an eventual invocation flag.)
  463. X */
  464. Xint        recursion;        /* Infinite recursion counter    */
  465. Xint        rec_recover = TRUE;    /* Unwind recursive macros    */
  466. X
  467. X/*
  468. X * instring is set TRUE when a string is scanned.  It modifies the
  469. X * behavior of the "get next character" routine, causing all characters
  470. X * to be passed to the caller (except <DEF_MAGIC>).  Note especially that
  471. X * comments and \<newline> are not removed from the source.  (This
  472. X * prevents cpp output lines from being arbitrarily long).
  473. X *
  474. X * inmacro is set by #define -- it absorbs comments and converts
  475. X * form-feed and vertical-tab to space, but returns \<newline>
  476. X * to the caller.  Strictly speaking, this is a bug as \<newline>
  477. X * shouldn't delimit tokens, but we'll worry about that some other
  478. X * time -- it is more important to prevent infinitly long output lines.
  479. X *
  480. X * instring and inmarcor are parameters to the get() routine which
  481. X * were made global for speed.
  482. X */
  483. Xint        instring = FALSE;    /* TRUE if scanning string    */
  484. Xint        inmacro = FALSE;    /* TRUE if #defining a macro    */
  485. X
  486. X/*
  487. X * work[] and workp are used to store one piece of text in a temporay
  488. X * buffer.  To initialize storage, set workp = work.  To store one
  489. X * character, call save(c);  (This will fatally exit if there isn't
  490. X * room.)  To terminate the string, call save(EOS).  Note that
  491. X * the work buffer is used by several subroutines -- be sure your
  492. X * data won't be overwritten.  The extra byte in the allocation is
  493. X * needed for string formal replacement.
  494. X */
  495. Xchar        work[NWORK + 1];    /* Work buffer            */
  496. Xchar        *workp;         /* Work buffer pointer        */
  497. X
  498. X/*
  499. X * keepcomments is set TRUE by the -C option.  If TRUE, comments
  500. X * are written directly to the output stream.  This is needed if
  501. X * the output from cpp is to be passed to lint (which uses commands
  502. X * embedded in comments).  cflag contains the permanent state of the
  503. X * -C flag.  keepcomments is always falsified when processing #control
  504. X * commands and when compilation is supressed by a false #if
  505. X *
  506. X * If eflag is set, CPP returns "success" even if non-fatal errors
  507. X * were detected.
  508. X *
  509. X * If nflag is non-zero, no symbols are predefined except __LINE__.
  510. X * __FILE__, and __DATE__.  If nflag > 1, absolutely no symbols
  511. X * are predefined.
  512. X */
  513. Xint        keepcomments = FALSE;    /* Write out comments flag    */
  514. Xint        cflag = FALSE;        /* -C option (keep comments)    */
  515. Xint        eflag = FALSE;        /* -E option (never fail)       */
  516. Xint        nflag = 0;        /* -N option (no predefines)    */
  517. Xint        wflag = FALSE;        /* -W option (write #defines)   */
  518. X
  519. X/*
  520. X * ifstack[] holds information about nested #if's.  It is always
  521. X * accessed via *ifptr.  The information is as follows:
  522. X *    WAS_COMPILING    state of compiling flag at outer level.
  523. X *    ELSE_SEEN    set TRUE when #else seen to prevent 2nd #else.
  524. X *    TRUE_SEEN    set TRUE when #if or #elif succeeds
  525. X * ifstack[0] holds the compiling flag.  It is TRUE if compilation
  526. X * is currently enabled.  Note that this must be initialized TRUE.
  527. X */
  528. Xchar        ifstack[BLK_NEST] = { TRUE };    /* #if information    */
  529. Xchar        *ifptr = ifstack;        /* -> current ifstack[] */
  530. X
  531. X/*
  532. X * incdir[] stores the -i directories (and the system-specific
  533. X * #include <...> directories.
  534. X */
  535. Xchar    *incdir[NINCLUDE];        /* -i directories        */
  536. Xchar    **incend = incdir;        /* -> free space in incdir[]    */
  537. X
  538. X/*
  539. X * This is the table used to predefine target machine and operating
  540. X * system designators.    It may need hacking for specific circumstances.
  541. X * Note: it is not clear that this is part of the Ansi Standard.
  542. X * The -N option supresses preset definitions.
  543. X */
  544. Xchar    *preset[] = {            /* names defined at cpp start    */
  545. X#ifdef    MACHINE
  546. X    MACHINE,
  547. X#endif
  548. X#ifdef    SYSTEM
  549. X    SYSTEM,
  550. X#endif
  551. X#ifdef    COMPILER
  552. X    COMPILER,
  553. X#endif
  554. X#if    DEBUG
  555. X    "decus_cpp",                    /* Ourselves!                   */
  556. X#endif
  557. X    NULL                /* Must be last         */
  558. X};
  559. X
  560. X/*
  561. X * The value of these predefined symbols must be recomputed whenever
  562. X * they are evaluated.    The order must not be changed.
  563. X */
  564. Xchar    *magic[] = {            /* Note: order is important    */
  565. X    "__LINE__",
  566. X    "__FILE__",
  567. X    NULL                /* Must be last         */
  568. X};
  569. X
  570. Xmain(argc, argv)
  571. Xint        argc;
  572. Xchar        *argv[];
  573. X{
  574. X    register int    i;
  575. X    extern FILE *freopen ();
  576. X
  577. X    DBUG_ENTER ("main");
  578. X    DBUG_PUSH ("d:t");
  579. X#if HOST == SYS_VMS
  580. X    argc = getredirection(argc, argv);      /* vms >file and <file  */
  581. X#endif
  582. X    initdefines();                          /* O.S. specific def's  */
  583. X    i = dooptions(argc, argv);              /* Command line -flags  */
  584. X    switch (i) {
  585. X    case 3:
  586. X        /*
  587. X         * Get output file, "-" means use stdout.
  588. X         */
  589. X        if (!streq(argv[2], "-")) {
  590. X#if HOST == SYS_VMS
  591. X        /*
  592. X         * On vms, reopen stdout with "vanilla rms" attributes.
  593. X         */
  594. X        if ((i = creat(argv[2], 0, "rat=cr", "rfm=var")) == -1
  595. X         || dup2(i, fileno(stdout)) == -1) {
  596. X#else
  597. X        if (freopen(argv[2], "w", stdout) == NULL) {
  598. X#endif
  599. X            perror(argv[2]);
  600. X            cerror("Can't open output file \"%s\"", argv[2]);
  601. X            exit(IO_ERROR);
  602. X        }
  603. X        }                /* Continue by opening input    */
  604. X    case 2:             /* One file -> stdin        */
  605. X        /*
  606. X         * Open input file, "-" means use stdin.
  607. X         */
  608. X        if (!streq(argv[1], "-")) {
  609. X        if (freopen(argv[1], "r", stdin) == NULL) {
  610. X            perror(argv[1]);
  611. X            cerror("Can't open input file \"%s\"", argv[1]);
  612. X            exit(IO_ERROR);
  613. X        }
  614. X        strcpy(work, argv[1]);  /* Remember input filename      */
  615. X        break;
  616. X        }                /* Else, just get stdin     */
  617. X    case 0:             /* No args?            */
  618. X    case 1:             /* No files, stdin -> stdout    */
  619. X#if HOST == SYS_UNIX || HOST == SYS_AMIGADOS
  620. X        work[0] = EOS;        /* Unix can't find stdin name   */
  621. X#else
  622. X        fgetname(stdin, work);      /* Vax-11C, Decus C know name   */
  623. X#endif
  624. X        break;
  625. X
  626. X    default:
  627. X        exit(IO_ERROR);             /* Can't happen                 */
  628. X    }
  629. X    setincdirs();                   /* Setup -I include directories */
  630. X    addfile(stdin, work);           /* "open" main input file       */
  631. X#if DEBUG
  632. X    if (debug > 0)
  633. X        dumpdef("preset #define symbols");
  634. X#endif
  635. X    cppmain();                      /* Process main file            */
  636. X    if ((i = (ifptr - &ifstack[0])) != 0) {
  637. X#if OLD_PREPROCESSOR
  638. X        ciwarn("Inside #ifdef block at end of input, depth = %d", i);
  639. X#else
  640. X        cierror("Inside #ifdef block at end of input, depth = %d", i);
  641. X#endif
  642. X    }
  643. X    fflush(stdout);
  644. X    fclose(stdout);
  645. X    if (errors > 0 && !eflag)
  646. X      DBUG_RETURN(IO_ERROR);
  647. X    DBUG_RETURN(IO_NORMAL);         /* No errors or -E option set   */
  648. X}
  649. X
  650. XFILE_LOCAL
  651. Xcppmain()
  652. X/*
  653. X * Main process for cpp -- copies tokens from the current input
  654. X * stream (main file, include file, or a macro) to the output
  655. X * file.
  656. X */
  657. X{
  658. X    register int        c;        /* Current character    */
  659. X    register int        counter;    /* newlines and spaces    */
  660. X    extern int        output();       /* Output one character */
  661. X
  662. X    DBUG_ENTER ("cppmain");
  663. X    /* Initialize for reading tokens */
  664. X    tokenbsize = 50;
  665. X    tokenbuf = getmem (tokenbsize + 1);
  666. X
  667. X    /*
  668. X     * Explicitly output a #line at the start of cpp output so
  669. X     * that lint (etc.) knows the name of the original source
  670. X     * file.  If we don't do this explicitly, we may get
  671. X     * the name of the first #include file instead.
  672. X     */
  673. X    sharp();
  674. X    /*
  675. X     * This loop is started "from the top" at the beginning of each line
  676. X     * wrongline is set TRUE in many places if it is necessary to write
  677. X     * a #line record.  (But we don't write them when expanding macros.)
  678. X     *
  679. X     * The counter variable has two different uses:  at
  680. X     * the start of a line, it counts the number of blank lines that
  681. X     * have been skipped over.  These are then either output via
  682. X     * #line records or by outputting explicit blank lines.
  683. X     * When expanding tokens within a line, the counter remembers
  684. X     * whether a blank/tab has been output.  These are dropped
  685. X     * at the end of the line, and replaced by a single blank
  686. X     * within lines.
  687. X     */
  688. X    for (;;) {
  689. X        counter = 0;            /* Count empty lines    */
  690. X        for (;;) {                          /* For each line, ...   */
  691. X        while (type[(c = get())] == SPA) /* Skip leading blanks */
  692. X            ;                /* in this line.    */
  693. X        if (c == '\n')                  /* If line's all blank, */
  694. X            ++counter;            /* Do nothing now    */
  695. X        else if (c == '#') {            /* Is 1st non-space '#' */
  696. X            keepcomments = FALSE;    /* Don't pass comments  */
  697. X            counter = control(counter); /* Yes, do a #command   */
  698. X            keepcomments = (cflag && compiling);
  699. X        }
  700. X        else if (c == EOF_CHAR)         /* At end of file?      */
  701. X            break;
  702. X        else if (!compiling) {          /* #ifdef false?        */
  703. X            skipnl();                   /* Skip to newline      */
  704. X            counter++;            /* Count it, too.    */
  705. X        }
  706. X        else {
  707. X            break;            /* Actual token     */
  708. X        }
  709. X        }
  710. X        if (c == EOF_CHAR)                  /* Exit process at      */
  711. X        break;                /* End of file        */
  712. X        /*
  713. X         * If the loop didn't terminate because of end of file, we
  714. X         * know there is a token to compile.  First, clean up after
  715. X         * absorbing newlines.  counter has the number we skipped.
  716. X         */
  717. X        if ((wrongline && infile->fp != NULL) || counter > 4)
  718. X        sharp();                        /* Output # line number */
  719. X        else {                /* If just a few, stuff */
  720. X        while (--counter >= 0)          /* them out ourselves   */
  721. X            putchar('\n');
  722. X        }
  723. X        /*
  724. X         * Process each token on this line.
  725. X         */
  726. X        unget();                            /* Reread the char.     */
  727. X        for (;;) {                          /* For the whole line,  */
  728. X        do {                /* Token concat. loop    */
  729. X            for (counter = 0; (type[(c = get())] == SPA);) {
  730. X#if COMMENT_INVISIBLE
  731. X            if (c != COM_SEP)
  732. X                counter++;
  733. X#else
  734. X            counter++;        /* Skip over blanks    */
  735. X#endif
  736. X            }
  737. X            if (c == EOF_CHAR || c == '\n')
  738. X            goto end_line;        /* Exit line loop    */
  739. X            else if (counter > 0)       /* If we got any spaces */
  740. X            putchar(' ');           /* Output one space     */
  741. X            c = macroid(c);             /* Grab the token       */
  742. X        } while (type[c] == LET && catenate());
  743. X        if (c == EOF_CHAR || c == '\n') /* From macro exp error */
  744. X            goto end_line;        /* Exit line loop    */
  745. X        switch (type[c]) {
  746. X        case LET:
  747. X            fputs(tokenbuf, stdout);    /* Quite ordinary token */
  748. X            break;
  749. X
  750. X
  751. X        case DIG:            /* Output a number    */
  752. X        case DOT:            /* Dot may begin floats */
  753. X            scannumber(c, output);
  754. X            break;
  755. X
  756. X        case QUO:            /* char or string const */
  757. X            scanstring(c, output);      /* Copy it to output    */
  758. X            break;
  759. X
  760. X        default:            /* Some other character */
  761. X            cput(c);                    /* Just output it       */
  762. X            break;
  763. X        }                /* Switch ends        */
  764. X        }                    /* Line for loop    */
  765. Xend_line:   if (c == '\n') {                    /* Compiling at EOL?    */
  766. X        putchar('\n');                  /* Output newline, if   */
  767. X        if (infile->fp == NULL)         /* Expanding a macro,   */
  768. X            wrongline = TRUE;        /* Output # line later    */
  769. X        }
  770. X    }                    /* Continue until EOF    */
  771. X    if (wflag)
  772. X        outdefines();                       /* Write out #defines   */
  773. X    DBUG_VOID_RETURN;
  774. X}
  775. X
  776. Xoutput(c)
  777. Xint        c;
  778. X/*
  779. X * Output one character to stdout -- output() is passed as an
  780. X * argument to scanstring()
  781. X */
  782. X{
  783. X#if COMMENT_INVISIBLE
  784. X    if (c != TOK_SEP && c != COM_SEP)
  785. X#else
  786. X    if (c != TOK_SEP)
  787. X#endif
  788. X        putchar(c);
  789. X}
  790. X
  791. Xstatic char    *sharpfilename = NULL;
  792. X
  793. XFILE_LOCAL
  794. Xsharp()
  795. X/*
  796. X * Output a line number line.
  797. X */
  798. X{
  799. X    register char        *name;
  800. X
  801. X    DBUG_ENTER ("sharp");
  802. X    if (keepcomments)                       /* Make sure # comes on */
  803. X        putchar('\n');                      /* a fresh, new line.   */
  804. X    printf("#%s %d", LINE_PREFIX, line);
  805. X    if (infile->fp != NULL) {
  806. X        name = (infile->progname != NULL)
  807. X        ? infile->progname : infile->filename;
  808. X        if (sharpfilename == NULL
  809. X         || sharpfilename != NULL && !streq(name, sharpfilename)) {
  810. X        if (sharpfilename != NULL)
  811. X            free(sharpfilename);
  812. X        sharpfilename = savestring(name);
  813. X        printf(" \"%s\"", name);
  814. X         }
  815. X    }
  816. X    putchar('\n');
  817. X    wrongline = FALSE;
  818. X    DBUG_VOID_RETURN;
  819. X}
  820. END_OF_FILE
  821. if test 26903 -ne `wc -c <'Cpp1.c'`; then
  822.     echo shar: \"'Cpp1.c'\" unpacked with wrong size!
  823. fi
  824. # end of 'Cpp1.c'
  825. fi
  826. echo shar: End of archive 4 \(of 5\).
  827. cp /dev/null ark4isdone
  828. MISSING=""
  829. for I in 1 2 3 4 5 ; do
  830.     if test ! -f ark${I}isdone ; then
  831.     MISSING="${MISSING} ${I}"
  832.     fi
  833. done
  834. if test "${MISSING}" = "" ; then
  835.     echo You have unpacked all 5 archives.
  836.     rm -f ark[1-9]isdone
  837. else
  838.     echo You still need to unpack the following archives:
  839.     echo "        " ${MISSING}
  840. fi
  841. ##  End of shell archive.
  842. exit 0
  843. -- 
  844. Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
  845.     amiga@cs.odu.edu    
  846. or    amiga@xanth.cs.odu.edu    ( obsolescent mailers may need this address )
  847. or    ...!uunet!xanth!amiga    ( very obsolescent mailers need this address )
  848.  
  849. Comments, questions, and suggestions s should be addressed to ``amiga-request''
  850. (only use ``amiga'' for submissions) at the above addresses.
  851.